﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LGE;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace Stealth
{
    public class Medic : Enemy
    {
        static Texture2D circleFullGreen = Engine.Load<Texture2D>("Images\\HUD\\circle_full_green");
        static Texture2D circleEdgeGreen = Engine.Load<Texture2D>("Images\\HUD\\circle_edge_green");
        static Texture2D circleFullYellow = Engine.Load<Texture2D>("Images\\HUD\\circle_full_yellow");
        static Texture2D circleEdgeYellow = Engine.Load<Texture2D>("Images\\HUD\\circle_edge_yellow");
        static Texture2D circleFullRed = Engine.Load<Texture2D>("Images\\HUD\\circle_full_red");
        static Texture2D circleEdgeRed = Engine.Load<Texture2D>("Images\\HUD\\circle_edge_red");
        static float maxGreen = .5f;
        static float maxYellow =.9f;

        static Vector2 circlePos = new Vector2(0, -90);
        static float distStart = 400; // dist para o circulo aparecer
        static float distEnd = 200; // dist para o médico ver o vamp
        static Point SightRange = new Point((int)distEnd, 100);
        static float vel = 1f;

        public Rectangle SightRect { get { return new Rectangle((int)position.X - SightRange.X / 2, (int)position.Y - SightRange.Y / 2, SightRange.X, SightRange.Y); } }

        double stateTimer = 0;
        double doorTimer = 10000;
        InteractiveObject door = null;

        float oldPosY = 0;

        public Medic(PlayScreen ps, Vector2 position)
            : base(ps, position, null)
        {
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Medic\\stand"), new SpriteSheet(this, 79, 114, 80, true)); // medico_stand-80ms79x114.png
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Medic\\walk"), new SpriteSheet(this, 79, 114, 80, true));
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Medic\\door_in"), new SpriteSheet(this, 120, 180, 40, false)); // DoorIn medico_portaIn-40ms120x180.png
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Medic\\door_out"), new SpriteSheet(this, 120, 200, 40, false)); // doorOut medico_portaOut-40ms120x180.png
            state.Change(States.Walk);
            state.Change(States.Idle);
            HitBox = new Rectangle(0, 0, 79, 114);
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            if (door == null && !ps.c.isStealth && SightRect.Intersects(ps.c.HitBox))
                ps.c.Die();

            if (door == null) CheckCollisionWithMap(gameTime);
            UpdateBehavior(gameTime);
        }

        public override void CheckCollisionWithMap(GameTime gameTime)
        {
            speed.Y += gravityAcc; // update gravity

            // update Position.X
            if (speed.X != 0)
            {
                position.X += speed.X;
                float dH = ps.CollisionH(this, speed.X < 0, true);
                if (dH != 0)
                {
                    position.X += dH;
                    isFacingLeft = !isFacingLeft;
                }
                speed.X = 0;
            }

            // update Position.Y
            position.Y += speed.Y;
            float dV = ps.CollisionV(this, speed.Y < 0, !onGround);
            if (dV != 0)
            {
                position.Y += dV + 0.001f * (speed.Y < 0 ? 1 : -1);
                if (speed.Y > 0)
                    onGround = true; // se estava caindo (não subindo), então agora está no chão pq colidiu (com o chão)
                speed.Y = 0;
            }
            else onGround = false;
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            base.Draw(spriteBatch);
            //spriteBatch.Draw(GameScreenManager.blackScreen, drawPosition - new Vector2(SightRange.X, SightRange.Y)/2, new Rectangle(0, 0, SightRange.X, SightRange.Y), new Color(1,1,1,.5f));
            float d = Vector2.Distance(position, ps.c.position);
            if (d < distStart)
            {
                Vector2 fullCirclePos = drawPosition + circlePos + new Vector2(15, 15);
                float scale = Math.Min(1, 1 - ((d - distEnd) / (distStart - distEnd)));

                spriteBatch.Draw(scale < maxGreen ? circleFullGreen : scale < maxYellow ? circleFullYellow : circleFullRed, fullCirclePos, null, Color.White, 0, new Vector2(15, 15), scale, SpriteEffects.None, 0);
                spriteBatch.Draw(scale < maxGreen ? circleEdgeGreen : scale < maxYellow ? circleEdgeYellow : circleEdgeRed, drawPosition + circlePos, Color.White);
            }
        }

        private void UpdateBehavior(GameTime gameTime)
        {
            stateTimer -= gameTime.ElapsedGameTime.TotalMilliseconds;
            doorTimer -= gameTime.ElapsedGameTime.TotalMilliseconds;

            switch (state.actualState)
            {
                case States.Idle:
                    speed.X = 0;
                    if (stateTimer < 0)
                    {
                        stateTimer = 0;
                        state.Change(States.Walk);
                        stateTimer = Rand.Next(3000, 7000); // tempo que vai ficar andando
                        isFacingLeft = Rand.NextBool();
                    }
                    break;
                case States.Walk:
                    speed.X = vel * (isFacingLeft ? -1 : 1);
                    if (doorTimer < 0)
                    {
                        door = GetCollidingDoor();
                        if (door != null && !door.isOccupied)
                        {
                            Audio.PlayCue("door");
                            oldPosY = position.Y;
                            door.isOccupied = true;
                            speed = Vector2.Zero;
                            isFacingLeft = false;
                            position = door.position;
                            doorTimer = Rand.Next(5000, 10000); // tempo que vai ficar dentro da sala
                            state.Change(States.DoorIn);
                        }
                    }
                    if (stateTimer < 0)
                    {
                        stateTimer = 0;
                        state.Change(States.Idle);
                        stateTimer = Rand.Next(2000, 6000); // tempo que vai ficar parado
                    }
                    break;
                case States.DoorIn:
                    if (state.completed && doorTimer < 0)
                    {
                        Audio.PlayCue("door");
                        state.Change(States.DoorOut);
                    }
                    break;
                case States.DoorOut:
                    if (state.completed)
                    {
                        state.Change(States.Walk);
                        doorTimer = Rand.Next(10000, 20000); // tempo até aceitar entrar em outra sala
                        door.isOccupied = false;
                        door = null;
                        position.Y = oldPosY;
                        position.X -= 20;
                        isFacingLeft = true;
                    }
                    break;
                default: break;
            }
        }

        private InteractiveObject GetCollidingDoor()
        {
            foreach (InteractiveObject door in ps.Doors)
                if (Collision(door))
                    return door;
            return null;
        }

        static class States
        {
            public const int Idle = 0;
            public const int Walk = 1;
            public const int DoorIn = 2;
            public const int DoorOut = 3;
        }
    }


}
